package personal.vivian.logic;

import groovy.lang.Binding;
import groovy.lang.GroovyClassLoader;
import groovy.lang.Script;
import lombok.extern.slf4j.Slf4j;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
public class GroovyCompiler {
    static Logger logger= LoggerFactory.getLogger(GroovyCompiler.class);

    private static Map<String,ClassCache> groovyCache = new ConcurrentHashMap<String,ClassCache>();
    public static ClassCache getCachedClass(File res){
        ClassCache classCache = groovyCache.get(res.getName());
        if(classCache!=null){
            return classCache;
        }else{
            return null;
        }
    }
    public static  GroovyClass getClass(File res){
        logger.info("getscript");
        GroovyClassLoader groovyClassLoader=new GroovyClassLoader();
        Map<String, Object> binds = new HashMap<>();
        Binding binding = new Binding(binds);
        Script script = null;
        ClassCache classCache = getCachedClass(res);
        if(classCache!=null){
            Script scri = InvokerHelper.createScript(classCache.getCls(),binding);
            return new GroovyClass<Script>(scri);
        }
        try {
            Class<?> scriptClass = groovyClassLoader.parseClass(res);
            groovyCache.put(res.getName(),new ClassCache(scriptClass,res.lastModified()));
            script = InvokerHelper.createScript(scriptClass, binding);
            return new GroovyClass<Script>(script);
        }catch (IOException e){
            logger.error("parseClass error");
        }
        return null;
    }
    public  static class ClassCache{
        private long lastmodified = 0;
        private Class cls;
        public ClassCache(Class cls,long lastmodified){
            this.cls = cls;
            this.lastmodified=lastmodified;
        }

        public long getLastmodified() {
            return lastmodified;
        }

        public void setLastmodified(long lastmodified) {
            this.lastmodified = lastmodified;
        }

        public Class getCls() {
            return cls;
        }

        public void setCls(Class cls) {
            this.cls = cls;
        }
    }
}
